package yanivosher.aiproject;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Yaniv n Osher
 * 
 */
public class Environment {
	private static Environment instance = null;

	public ArrayList<Agent> agents;
	public Graph graph;

	public int noOpCost = 0;
	public int hellBreaksLooseCost = 999999999;
	public int fCost = 1;

	protected Environment() {
		agents = new ArrayList<Agent>();
		graph = new Graph(new ArrayList<Vertex>(), new ArrayList<Edge>());
	}

	public static Environment getInstance() {
		if (instance == null) {
			instance = new Environment();
		}
		return instance;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("\n");
		sb.append(duplicateString("###", 6) + "\n");
		sb.append("Agents:");
		sb.append("\n");
		int index = 0;
		for (Agent agent : agents) {
			sb.append(duplicateString("###", 6) + "\n");
			sb.append("Agent #" + index++);
			sb.append("\n");
			sb.append("Agent score:" + agent.score);
			sb.append("\n");
			sb.append("Agent vertex:" + agent.currentVertex.getId());
			sb.append("\n");
			sb.append(duplicateString("###", 6) + "\n");
		}

		sb.append("\n");
		for (Vertex vertex : graph.getVertexes()) {
			sb.append(duplicateString("###", 6) + "\n");
			sb.append("Vertex : " + vertex.getId() + "\n");
			sb.append(duplicateString("###", 6) + "\n");
			sb.append("Agents : " + getAgentsInVertex(vertex) + "\n");
			sb.append("Chems  : " + vertex.getChem() + "\n");
			sb.append("Militry: " + vertex.getMilitary() + "\n");
			sb.append(duplicateString("###", 6) + "\n\n");
		}

		sb.append(duplicateString("###", 6) + "\n");

		sb.append("	#");
		for (Vertex vertexRow : graph.getVertexes()) {
			sb.append(vertexRow.getId() + "       		#");
		}
		sb.append("\n");

		for (Vertex vertexRow : graph.getVertexes()) {
			// Weight:
			sb.append(vertexRow.getId() + "	#");
			for (Vertex vertexCol : graph.getVertexes()) {
				Edge e = graph.getEdgeBySourceDestination(vertexRow, vertexCol);
				if (e != null) {
					sb.append("Weight: " + e.getWeight() + "		#");
				} else {
					sb.append("       		#");
				}
			}
			sb.append("\n");
			sb.append("	#");
			// Block :
			for (Vertex vertexCol : graph.getVertexes()) {
				Edge e = graph.getEdgeBySourceDestination(vertexRow, vertexCol);
				if (e != null) {
					sb.append("Block : " + e.getIsBlocked() + "		#");
				} else {
					sb.append("       		#");
				}
			}
			sb.append("\n"
					+ duplicateString("###########################",
							graph.getVertexes().size()) + "\n");
		}

		return sb.toString();
	}

	private static String duplicateString(String str, int count) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < count; i++) {
			sb.append(str);
		}
		return sb.toString();
	}

	private String getAgentsInVertex(Vertex vertex) {
		StringBuilder sb = new StringBuilder();
		int index = 0;
		for (Agent agent : agents) {
			if (agent.currentVertex.equals(vertex)) {
				sb.append(index + ",");
			}
			index++;
		}
		return sb.toString();
	}

	public boolean everyoneInPlace() {
		for (Agent agent : agents) {
			if (!agent.idDone()/*!agent.currentVertex.equals(agent.destinationVertex)*/) {
				return false;
			}
		}
		return true;
	}

	//Return new graph with the weight with chems (without military).
	public Graph reweightedBlockedGraph() {
		ArrayList<Edge> newEdges = new ArrayList<Edge>();
		for (Edge edge : graph.getEdges()) {
			Edge newEdge;
			if (edge.getIsBlocked()) {
				newEdge = new Edge(edge.getId(), edge.getSource(), edge.getDestination(), edge.getWeight()*this.hellBreaksLooseCost);
			}
			else
			{
				newEdge = new Edge(edge.getId(), edge.getSource(), edge.getDestination(), edge.getWeight()*this.hellBreaksLooseCost);
			}
			newEdges.add(newEdge);
		}
		return new Graph(this.graph.getVertexes(), newEdges);
	}

	public static void printPath(List<Vertex> path) {
		StringBuilder sb = new StringBuilder("Path: ");
		if (path == null) {
			sb.append("null");
		}
		else
		{
			for (Vertex vertex : path) {
				sb.append(vertex.getName() + ",");
			}
		}
		System.out.println(sb.toString());
	}
}
